#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
异常处理完整测试套件

测试异常处理的所有场景，包括：
1. 基础异常抛出和捕获
2. 异常消息格式（字面量、运行时、f-string）
3. 控制流（try/except/else/finally）
4. 循环中的异常处理（break/continue/return）
5. finally 覆盖控制流
6. 嵌套异常
7. 作用域
"""

from gtest import test, EXPECT_EQ, EXPECT_TRUE, EXPECT_FALSE


# 全局变量用于验证 finally 执行
g_finally_executed: int = 0

# ============================================================================
# 1. 基础异常类型测试
# ============================================================================


@test("Exception", "ValueError")
def test_value_error():
    """测试 ValueError 的抛出和捕获"""
    exception_caught: bool = False
    exception_message: str = ""

    try:
        raise ValueError("invalid value")
    except ValueError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_TRUE("invalid" in exception_message or len(exception_message) > 0)


@test("Exception", "TypeError")
def test_type_error():
    """测试 TypeError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise TypeError("type mismatch")
    except TypeError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("Exception", "RuntimeError")
def test_runtime_error():
    """测试 RuntimeError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise RuntimeError("runtime error occurred")
    except RuntimeError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("Exception", "IndexError")
def test_index_error():
    """测试 IndexError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise IndexError("index out of range")
    except IndexError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("Exception", "KeyError")
def test_key_error():
    """测试 KeyError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise KeyError("key not found")
    except KeyError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("Exception", "ZeroDivisionError")
def test_zero_division_error():
    """测试 ZeroDivisionError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise ZeroDivisionError("division by zero")
    except ZeroDivisionError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("Exception", "NotImplementedError")
def test_not_implemented_error():
    """测试 NotImplementedError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise NotImplementedError("not implemented yet")
    except NotImplementedError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("Exception", "AttributeError")
def test_attribute_error():
    """测试 AttributeError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise AttributeError("attribute not found")
    except AttributeError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("Exception", "NameError")
def test_name_error():
    """测试 NameError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise NameError("name not defined")
    except NameError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("Exception", "OverflowError")
def test_overflow_error():
    """测试 OverflowError 的抛出和捕获"""
    exception_caught: bool = False

    try:
        raise OverflowError("numeric overflow")
    except OverflowError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


# ============================================================================
# 2. 异常消息格式测试
# ============================================================================


@test("ExceptionMessage", "LiteralConstant")
def test_literal_constant():
    """测试字面量常量异常消息

    Python: raise ValueError("simple message")
    C++:    MC_THROW(mcpy::value_error, "simple message");
    """
    exception_caught: bool = False
    exception_message: str = ""

    try:
        raise ValueError("simple message")
    except ValueError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(exception_message, "simple message")


@test("ExceptionMessage", "LiteralWithPlaceholders")
def test_literal_with_placeholders():
    """测试包含占位符的字面量（占位符应该被转义）

    Python: raise ValueError("Use {x} and ${y}")
    C++:    MC_THROW(mcpy::value_error, "Use {{x}} and $${{y}}");

    占位符应该被转义后原样输出
    """
    exception_caught: bool = False
    exception_message: str = ""

    try:
        raise ValueError("Use {x} and ${y}")
    except ValueError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    # libmcpp 转义行为：$${{y}} → ${{y}}
    EXPECT_EQ(exception_message, "Use {x} and ${{y}}")


@test("ExceptionMessage", "RuntimeExpression")
def test_runtime_expression():
    """测试运行时表达式（安全包装，防止格式化注入）

    Python: raise ValueError(msg + str(value))
    C++:    MC_THROW(mcpy::value_error, "{}", (msg + mc::to_string(value)));

    使用位置占位符 {}，参数自动按位置匹配
    """
    exception_caught: bool = False
    exception_message: str = ""

    msg: str = "Error code: "
    value: int = 42

    try:
        raise ValueError(msg + str(value))
    except ValueError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(exception_message, "Error code: 42")


@test("ExceptionMessage", "RuntimeExpressionSafety")
def test_runtime_expression_safety():
    """测试运行时表达式的安全性（防格式化注入）

    恶意字符串包含 ${} 占位符，应该被转义，不会被解析
    运行时字符串会被安全包装，占位符原样输出
    """
    exception_caught: bool = False
    exception_message: str = ""

    malicious_input: str = "Error ${system_var}"

    try:
        raise ValueError(malicious_input)
    except ValueError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(exception_message, "Error ${system_var}")


@test("ExceptionMessage", "FString")
def test_fstring():
    """测试 f-string 格式化

    Python: raise ValueError(f"Value {value} is out of range")
    C++:    MC_THROW(mcpy::value_error, "Value {} is out of range", (value));

    f-string 中的 {} 直接映射为 libmcpp 的位置占位符 {}
    """
    exception_caught: bool = False
    exception_message: str = ""

    value: int = 42

    try:
        raise ValueError(f"Value {value} is out of range")
    except ValueError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(exception_message, "Value 42 is out of range")


@test("ExceptionMessage", "FStringMultipleArgs")
def test_fstring_multiple_args():
    """测试多参数 f-string

    Python: raise ValueError(f"Value {value} range {min_val}-{max_val}")
    C++:    MC_THROW(mcpy::value_error, "Value {} range {}-{}", (value)(min_val)(max_val));

    多个 {} 按位置顺序自动匹配参数，使用链式调用 (arg1)(arg2)(arg3)
    """
    exception_caught: bool = False
    exception_message: str = ""

    value: int = 150
    min_val: int = 0
    max_val: int = 100

    try:
        raise ValueError(f"Value {value} range {min_val}-{max_val}")
    except ValueError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(exception_message, "Value 150 range 0-100")


@test("ExceptionMessage", "FStringComplexExpression")
def test_fstring_complex_expression():
    """测试包含复杂表达式的 f-string

    表达式在格式化前求值：x + y * 2 = 10 + 5 * 2 = 20
    """
    exception_caught: bool = False
    exception_message: str = ""

    x: int = 10
    y: int = 5

    try:
        raise ValueError(f"Result: {x + y * 2}")
    except ValueError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(exception_message, "Result: 20")


@test("ExceptionMessage", "EmptyMessage")
def test_empty_message():
    """测试空消息异常

    Python: raise ValueError()
    C++:    throw mcpy::value_error();

    无参数时使用默认构造函数，不使用 MC_MAKE_EXCEPTION
    """
    exception_caught: bool = False

    try:
        raise ValueError()
    except ValueError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


# ============================================================================
# 3. 多异常处理测试
# ============================================================================


@test("ExceptionHandling", "MultipleExceptionHandlers")
def test_multiple_exception_handlers():
    """测试多个异常处理器的匹配顺序"""
    result: int = 0

    # 测试 ValueError
    try:
        raise ValueError("test")
    except ValueError:
        result = 1
    except TypeError:
        result = 2
    except RuntimeError:
        result = 3

    EXPECT_EQ(result, 1)

    # 测试 TypeError
    try:
        raise TypeError("test")
    except ValueError:
        result = 1
    except TypeError:
        result = 2
    except RuntimeError:
        result = 3

    EXPECT_EQ(result, 2)


@test("ExceptionHandling", "CatchAllExceptions")
def test_catch_all_exceptions():
    """测试捕获所有异常（bare except）"""
    exception_caught: bool = False

    try:
        raise ValueError("test")
    except:
        exception_caught = True

    EXPECT_TRUE(exception_caught)

    exception_caught = False
    try:
        raise TypeError("test")
    except:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("ExceptionHandling", "BareRaise")
def test_bare_raise():
    """测试不带参数的 raise 语句（重新抛出当前异常）

    验证 bare raise 保持原始异常的完整信息
    """
    exception_caught: bool = False
    exception_message: str = ""

    try:
        raise ValueError("test")
    except ValueError:
        try:
            raise  # 重新抛出当前异常
        except ValueError as e:
            exception_caught = True
            exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(exception_message, "test")


@test("ExceptionHandling", "BareExceptWithFinally")
def test_bare_except_with_finally():
    """测试 bare except with finally

    验证：
    1. bare except 捕获所有异常（包括 C++ 标准库异常）
    2. finally 正常执行
    3. 异常不会重新抛出（已被 bare except 捕获处理）
    """
    result: int = 0

    try:
        raise ValueError("test")
    except:  # bare except
        result = 1
    finally:
        result = result + 10

    EXPECT_EQ(result, 11)  # 异常被捕获，不会重新抛出，继续执行


@test("ExceptionHandling", "BareExceptCatchesAllTypes")
def test_bare_except_catches_all_types():
    """测试 bare except 捕获所有类型的异常

    验证：bare except 生成 catch(...)，可以捕获所有异常
    """
    caught_count: int = 0

    # 捕获 ValueError
    try:
        raise ValueError("test1")
    except:
        caught_count = caught_count + 1

    # 捕获 TypeError
    try:
        raise TypeError("test2")
    except:
        caught_count = caught_count + 1

    # 捕获 RuntimeError
    try:
        raise RuntimeError("test3")
    except:
        caught_count = caught_count + 1

    EXPECT_EQ(caught_count, 3)


@test("ExceptionHandling", "ExceptRaiseWithFinally")
def test_except_raise_with_finally():
    """测试 except 块中 raise 新异常时 finally 的执行

    这是一个关键场景：验证 except 块中抛出新异常时，finally 仍会执行
    """
    global g_finally_executed
    g_finally_executed = 0
    exception_caught: bool = False

    try:
        try:
            raise ValueError("inner")
        except ValueError:
            g_finally_executed = 1
            raise RuntimeError("outer")  # 抛出新异常
        finally:
            g_finally_executed = 99  # 必须执行
    except RuntimeError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(g_finally_executed, 99)  # 验证 finally 确实执行了


@test("ExceptionHandling", "ElseRaiseWithFinally")
def test_else_raise_with_finally():
    """测试 else 块中 raise 时 finally 的执行

    验证 try/except/else/finally 中，else 块抛出异常时 finally 仍会执行
    """
    global g_finally_executed
    g_finally_executed = 0
    exception_caught: bool = False

    try:
        try:
            x: int = 1  # 不抛异常
        except ValueError:
            g_finally_executed = 1
        else:
            g_finally_executed = 2
            raise RuntimeError("from else")  # else 块中抛出异常
        finally:
            g_finally_executed = 99  # 必须执行
    except RuntimeError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(g_finally_executed, 99)  # 验证 finally 确实执行了


@test("ExceptionHandling", "BareRaiseWithFinally")
def test_bare_raise_with_finally():
    """测试 bare raise（重新抛出）时 finally 的执行

    验证 except 块中的 bare raise 也会执行 finally
    """
    global g_finally_executed
    g_finally_executed = 0
    exception_caught: bool = False

    try:
        try:
            raise ValueError("test")
        except ValueError:
            g_finally_executed = 1
            raise  # 重新抛出当前异常
        finally:
            g_finally_executed = 99  # 必须执行
    except ValueError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(g_finally_executed, 99)  # 验证 finally 确实执行了


@test("ExceptionHandling", "RaiseInIfWithFinally")
def test_raise_in_if_with_finally():
    """测试 except 块中嵌套 if 语句里的 raise

    验证复杂语句上下文（if/else）中的 raise 也会正确执行 finally
    """
    global g_finally_executed
    g_finally_executed = 0
    exception_caught: bool = False
    condition: bool = True

    try:
        try:
            raise ValueError("test")
        except ValueError:
            g_finally_executed = 1
            if condition:
                g_finally_executed = 2
                raise RuntimeError("from if")  # if 块中抛出
            else:
                g_finally_executed = 3
        finally:
            g_finally_executed = 99  # 必须执行
    except RuntimeError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(g_finally_executed, 99)  # 验证 finally 确实执行了


# ============================================================================
# 4. try/except/else/finally 控制流测试
# ============================================================================


@test("ControlFlow", "TryElseBasic")
def test_try_else_basic():
    """测试 else 块只在无异常时执行"""
    result: int = 0

    # 场景1: 无异常，执行 else
    try:
        x: int = 1 + 1
    except ValueError:
        result = 1
    else:
        result = 2

    EXPECT_EQ(result, 2)

    # 场景2: 有异常被捕获，不执行 else
    try:
        raise ValueError("error")
    except ValueError:
        result = 3
    else:
        result = 4

    EXPECT_EQ(result, 3)


@test("ControlFlow", "ElseNotExecutedWhenExceptionUncaught")
def test_else_not_executed_when_exception_uncaught():
    """测试异常未被捕获时，else 不执行"""
    result: int = 0

    try:
        try:
            raise RuntimeError("test")
        except ValueError:  # 不匹配
            result = 1
        else:
            result = 2  # 不应执行
    except RuntimeError:
        result = 3  # 应该执行

    EXPECT_EQ(result, 3)


@test("ControlFlow", "FinallyExecutesOnNormalFlow")
def test_finally_executes_on_normal_flow():
    """测试正常流程下 finally 执行"""
    executed: bool = False
    try:
        x: int = 10
    finally:
        executed = True

    EXPECT_TRUE(executed)


@test("ControlFlow", "FinallyExecutesOnException")
def test_finally_executes_on_exception():
    """测试异常发生时 finally 执行"""
    executed: bool = False

    try:
        try:
            raise ValueError("test")
        finally:
            executed = True
    except ValueError:
        pass

    EXPECT_TRUE(executed)


@test("ControlFlow", "MultipleFinallyInSameFunction")
def test_multiple_finally_in_same_function():
    """测试同一函数中多个 finally 子句"""
    count: int = 0

    # 第一个 try/finally
    try:
        count = count + 1
    finally:
        count = count + 10

    # 第二个 try/finally
    try:
        count = count + 100
    finally:
        count = count + 1000

    # 预期：1 + 10 + 100 + 1000 = 1111
    EXPECT_EQ(count, 1111)


# ============================================================================
# 5. 循环中的异常处理 - try 块中的控制流
# ============================================================================


def try_break_helper() -> int:
    """测试 try 块中的 break"""
    count: int = 0
    for i in range(10):
        try:
            if i == 3:
                break
            count = count + 1
        except ValueError:
            pass
        finally:
            count = count + 100

    return count


@test("LoopException", "TryBreak")
def test_try_break():
    """测试 try 块中 break，finally 仍执行"""
    result: int = try_break_helper()
    # i=0,1,2: count +1 +100 = 101 * 3 = 303
    # i=3: break, count +100 = 403
    EXPECT_EQ(result, 403)


def try_continue_helper() -> int:
    """测试 try 块中的 continue"""
    count: int = 0
    for i in range(5):
        try:
            if i == 2:
                continue
            count = count + 1
        except ValueError:
            pass
        finally:
            count = count + 10

    return count


@test("LoopException", "TryContinue")
def test_try_continue():
    """测试 try 块中 continue，finally 仍执行"""
    result: int = try_continue_helper()
    # i=0,1,3,4: count +1 +10 = 11 * 4 = 44
    # i=2: continue, count +10 = 54
    EXPECT_EQ(result, 54)


# ============================================================================
# 6. 循环中的异常处理 - except 块中的控制流
# ============================================================================


def except_break_helper() -> int:
    """测试 except 块中的 break"""
    count: int = 0
    for i in range(10):
        try:
            if i >= 5:
                raise ValueError("test")
            count = count + 1
        except ValueError:
            count = count + 100
            if i == 5:
                break
        finally:
            count = count + 10

    return count


@test("LoopException", "ExceptBreak")
def test_except_break():
    """测试 except 块中 break，finally 仍执行"""
    result: int = except_break_helper()
    # i=0,1,2,3,4: count +1 +10 = 11 * 5 = 55
    # i=5: raise, count +100 +10 = 165, then break
    EXPECT_EQ(result, 165)


def except_continue_helper() -> int:
    """测试 except 块中的 continue"""
    count: int = 0
    for i in range(5):
        try:
            if i >= 2:
                raise ValueError("test")
            count = count + 1
        except ValueError:
            if i == 3:
                continue  # 跳过 count + 100
            count = count + 100
        finally:
            count = count + 10

    return count


@test("LoopException", "ExceptContinue")
def test_except_continue():
    """测试 except 块中 continue，finally 仍执行"""
    result: int = except_continue_helper()
    # i=0,1: count +1 +10 = 11 * 2 = 22
    # i=2: raise, count +100 +10 = 132
    # i=3: raise, continue, count +10 = 142
    # i=4: raise, count +100 +10 = 252
    EXPECT_EQ(result, 252)


# ============================================================================
# 7. 循环中的异常处理 - else 块中的控制流
# ============================================================================


def else_break_helper() -> int:
    """测试 else 块中的 break"""
    count: int = 0
    for i in range(10):
        try:
            x: int = i
        except ValueError:
            pass
        else:
            if i == 5:
                break
        finally:
            count = count + 1

    return count


@test("LoopException", "ElseBreak")
def test_else_break():
    """测试 else 块中的 break，finally 仍执行"""
    result: int = else_break_helper()
    # break 时 i=5，所以循环执行了 6 次（0-5），count 应该是 6
    EXPECT_EQ(result, 6)


def else_continue_helper() -> int:
    """测试 else 块中的 continue"""
    count: int = 0
    total: int = 0
    for i in range(5):
        try:
            x: int = i
        except ValueError:
            pass
        else:
            if i == 2:
                continue
            total = total + i
        finally:
            count = count + 1

    return count * 100 + total


@test("LoopException", "ElseContinue")
def test_else_continue():
    """测试 else 块中的 continue，finally 仍执行"""
    result: int = else_continue_helper()
    # count=5, total=0+1+3+4=8, result=508
    EXPECT_EQ(result, 508)


# ============================================================================
# 8. finally 覆盖控制流 - return
# ============================================================================


def try_return_helper() -> int:
    """测试 try 中 return，finally 仍执行"""
    global g_finally_executed
    try:
        return 10
    finally:
        g_finally_executed = 99  # finally 执行，修改全局状态


@test("FinallyOverride", "TryReturn")
def test_try_return():
    """测试 try 中 return，finally 仍执行

    验证：return 值为 10，但 finally 块确实执行了（g_finally_executed 被修改为 99）
    """
    global g_finally_executed
    g_finally_executed = 0
    value: int = try_return_helper()
    EXPECT_EQ(value, 10)
    EXPECT_EQ(g_finally_executed, 99)  # 验证 finally 确实执行了


def except_return_helper() -> int:
    """测试 except 中 return，finally 仍执行"""
    global g_finally_executed
    try:
        raise ValueError("error")
    except ValueError:
        return 20
    finally:
        g_finally_executed = 99  # finally 执行，修改全局状态


@test("FinallyOverride", "ExceptReturn")
def test_except_return():
    """测试 except 中 return，finally 仍执行

    验证：return 值为 20，但 finally 块确实执行了（g_finally_executed 被修改为 99）
    """
    global g_finally_executed
    g_finally_executed = 0
    value: int = except_return_helper()
    EXPECT_EQ(value, 20)
    EXPECT_EQ(g_finally_executed, 99)  # 验证 finally 确实执行了


def else_return_helper() -> int:
    """测试 else 块中的 return"""
    global g_finally_executed
    x: int = 0
    try:
        x = 10
    except ValueError:
        g_finally_executed = 1
        return 0
    else:
        g_finally_executed = 2
        return x
    finally:
        g_finally_executed = 99  # finally 执行，覆盖 else 中的赋值


@test("FinallyOverride", "ElseReturn")
def test_else_return():
    """测试 else 块中的 return，finally 仍执行

    验证：return 值为 10，but finally 块确实执行了（g_finally_executed 被修改为 99）
    """
    global g_finally_executed
    g_finally_executed = 0
    result: int = else_return_helper()
    EXPECT_EQ(result, 10)
    EXPECT_EQ(g_finally_executed, 99)  # 验证 finally 确实执行了


def finally_return_override_try() -> int:
    """测试 finally 块中的 return 覆盖 try 的 return"""
    try:
        return 10
    finally:
        return 20  # type: ignore


@test("FinallyOverride", "FinallyReturnOverrideTry")
def test_finally_return_override_try():
    """测试 finally 中的 return 覆盖 try 中的 return"""
    result: int = finally_return_override_try()
    EXPECT_EQ(result, 20)


def finally_return_override_except() -> int:
    """测试 finally 块中的 return 覆盖 except 的 return"""
    try:
        raise ValueError("test")
    except ValueError:
        return 30
    finally:
        return 40  # type: ignore


@test("FinallyOverride", "FinallyReturnOverrideExcept")
def test_finally_return_override_except():
    """测试 finally 中的 return 覆盖 except 中的 return"""
    result: int = finally_return_override_except()
    EXPECT_EQ(result, 40)


def finally_return_override_else() -> int:
    """测试 finally 块中的 return 覆盖 else 的 return"""
    try:
        x: int = 10
    except ValueError:
        return 50
    else:
        return 60
    finally:
        return 70  # type: ignore


@test("FinallyOverride", "FinallyReturnOverrideElse")
def test_finally_return_override_else():
    """测试 finally 中的 return 覆盖 else 中的 return"""
    result: int = finally_return_override_else()
    EXPECT_EQ(result, 70)


# ============================================================================
# 9. finally 覆盖控制流 - break（循环中）
# ============================================================================


def finally_break_override_try() -> int:
    """测试 finally 块中的 break 覆盖 try 的 break"""
    count: int = 0
    for i in range(10):
        try:
            if i == 3:
                break  # try 中的 break
        finally:
            count = count + 1
            if i == 7:
                # finally 中的 break（但 i=3 时就退出了）
                break  # type: ignore

    return count


@test("FinallyOverride", "FinallyBreakEffective")
def test_finally_break_effective():
    """测试 try 中 break 时 finally 仍执行，但 finally 的 break 不会到达"""
    result: int = finally_break_override_try()
    # try 中 i=3 时 break，finally 执行后退出，count=4（i=0,1,2,3）
    EXPECT_EQ(result, 4)


def finally_break_override_try_direct() -> int:
    """测试 finally 块中直接 break"""
    count: int = 0
    for i in range(10):
        try:
            count = count + 1
        finally:
            if i == 3:
                break  # type: ignore

    return count


@test("FinallyOverride", "FinallyBreakDirect")
def test_finally_break_direct():
    """测试 finally 中直接 break"""
    result: int = finally_break_override_try_direct()
    # i=0,1,2,3: count +1 = 4
    EXPECT_EQ(result, 4)


def finally_break_override_except() -> int:
    """测试 finally 块中的 break 覆盖 except 中的 continue"""
    count: int = 0
    total: int = 0
    for i in range(10):
        try:
            if i >= 5:
                raise ValueError("test")
            count = count + 1
        except ValueError:
            total = total + 1
            continue  # except 中的 continue
        finally:
            if i == 7:
                break  # type: ignore

    return count * 100 + total


@test("FinallyOverride", "FinallyBreakOverrideExceptContinue")
def test_finally_break_override_except_continue():
    """测试 finally 中的 break 覆盖 except 中的 continue"""
    result: int = finally_break_override_except()
    # i=0,1,2,3,4: count +1 = 5
    # i=5,6: raise, total +1 = 2, continue
    # i=7: raise, total +1 = 3, continue 被 finally break 覆盖
    EXPECT_EQ(result, 503)


# ============================================================================
# 10. finally 覆盖控制流 - continue（循环中）
# ============================================================================


def finally_continue_override_try() -> int:
    """测试 finally 块中的 continue 覆盖 try 的普通流程"""
    count: int = 0
    total: int = 0
    for i in range(5):
        try:
            count = count + 1
        finally:
            if i == 2:
                continue  # type: ignore
            total = total + i

    return count * 100 + total


@test("FinallyOverride", "FinallyContinueDirect")
def test_finally_continue_direct():
    """测试 finally 中直接 continue"""
    result: int = finally_continue_override_try()
    # i=0,1,2,3,4: count +1 = 5
    # i=0,1,3,4: total +i = 8（跳过 i=2）
    EXPECT_EQ(result, 508)


def finally_continue_override_break() -> int:
    """测试 finally 块中的 continue 覆盖 try 的 break"""
    count: int = 0
    for i in range(10):
        try:
            count = count + 1
            if i == 3:
                break  # try 中的 break
        finally:
            if i == 3:
                continue  # type: ignore

    return count


@test("FinallyOverride", "FinallyContinueOverrideTryBreak")
def test_finally_continue_override_try_break():
    """测试 finally 中的 continue 覆盖 try 中的 break"""
    result: int = finally_continue_override_break()
    # i=0,1,2: count +1 = 3
    # i=3: count +1 = 4, break 被 finally continue 覆盖，继续循环
    # i=4,5,6,7,8,9: count +1 = 10
    EXPECT_EQ(result, 10)


def finally_continue_override_except_break() -> int:
    """测试 finally 块中的 continue 覆盖 except 的 break"""
    count: int = 0
    for i in range(10):
        try:
            if i >= 5:
                raise ValueError("test")
            count = count + 1
        except ValueError:
            count = count + 100
            if i == 5:
                break  # except 中的 break
        finally:
            if i == 5:
                continue  # type: ignore

    return count


@test("FinallyOverride", "FinallyContinueOverrideExceptBreak")
def test_finally_continue_override_except_break():
    """测试 finally 中的 continue 覆盖 except 中的 break"""
    result: int = finally_continue_override_except_break()
    # i=0,1,2,3,4: count +1 = 5
    # i=5: raise, count +100 = 105, break 被 finally continue 覆盖
    # i=6,7,8,9: raise, count +100 = 505
    EXPECT_EQ(result, 505)


def finally_return_override_break() -> int:
    """测试 finally 块中的 return 覆盖 try 的 break"""
    count: int = 0
    for i in range(10):
        try:
            count = count + 1
            if i == 3:
                break  # try 中的 break
        finally:
            if i == 3:
                return count  # type: ignore

    return count


@test("FinallyOverride", "FinallyReturnOverrideTryBreak")
def test_finally_return_override_try_break():
    """测试 finally 中的 return 覆盖 try 中的 break"""
    result: int = finally_return_override_break()
    # i=0,1,2,3: count +1 = 4，i=3 时 return
    EXPECT_EQ(result, 4)


# ============================================================================
# 11. 嵌套异常测试
# ============================================================================


@test("NestedExceptions", "NestedTryExcept")
def test_nested_try_except():
    """测试嵌套的 try/except"""
    outer_caught: bool = False
    inner_caught: bool = False

    try:
        try:
            raise ValueError("inner error")
        except ValueError:
            inner_caught = True
            raise RuntimeError("outer error")
    except RuntimeError:
        outer_caught = True

    EXPECT_TRUE(inner_caught)
    EXPECT_TRUE(outer_caught)


def nested_finally_return() -> int:
    """测试嵌套 finally 的执行顺序"""
    global g_finally_executed
    try:
        try:
            return 10
        finally:
            g_finally_executed = g_finally_executed + 1  # inner finally，先执行
    finally:
        g_finally_executed = g_finally_executed + 10  # outer finally，后执行


@test("NestedExceptions", "NestedFinallyReturn")
def test_nested_finally_return():
    """测试嵌套 finally 的执行顺序

    验证：
    1. 返回值为 10（inner try 的 return）
    2. inner finally 先执行（g_finally_executed: 0 → 1）
    3. outer finally 后执行（g_finally_executed: 1 → 11）
    """
    global g_finally_executed
    g_finally_executed = 0
    result: int = nested_finally_return()
    EXPECT_EQ(result, 10)
    EXPECT_EQ(g_finally_executed, 11)  # 验证两个 finally 都执行了：0 + 1 + 10 = 11


def nested_finally_exception() -> int:
    """测试嵌套 finally 的异常处理"""
    result: int = 0
    try:
        try:
            raise ValueError("inner")
        except ValueError:
            result = result + 1
        finally:
            result = result + 10  # inner finally
    except RuntimeError:
        result = result + 100
    finally:
        result = result + 1000  # outer finally

    return result


@test("NestedExceptions", "NestedFinallyException")
def test_nested_finally_exception():
    """测试嵌套 finally 的异常处理"""
    result: int = nested_finally_exception()
    # inner exception 被捕获 (result=1) → inner finally (result=11) → outer finally (result=1011)
    EXPECT_EQ(result, 1011)


def nested_finally_with_code_after() -> int:
    """测试内层 try/except/finally 之后的正常代码执行时机

    验证控制流：
    1. inner try/except/finally 执行完毕
    2. 继续执行外层 try 块中 inner finally 之后的正常代码
    3. 最后执行外层 finally
    """
    result: int = 0
    try:
        try:
            raise ValueError("inner")
        except ValueError:
            result = result + 1  # inner except
        finally:
            result = result + 10  # inner finally

        # 内层 try/except/finally 之后的正常代码
        # 这段代码应该在 inner finally 之后、outer finally 之前执行
        result = result + 100

    finally:
        result = result + 1000  # outer finally

    return result


@test("NestedExceptions", "NestedFinallyWithCodeAfter")
def test_nested_finally_with_code_after():
    """测试内层 finally 之后的正常代码执行时机

    验证执行顺序：
    1. inner except: result = 1
    2. inner finally: result = 11
    3. 正常代码: result = 111 （inner finally 之后、outer finally 之前）
    4. outer finally: result = 1111

    这个测试验证了 inner finally 执行后，控制流正常返回继续执行后续代码
    """
    result: int = nested_finally_with_code_after()
    EXPECT_EQ(result, 1111)


def nested_finally_with_return_after() -> int:
    """测试内层 finally 之后有 return 的场景

    验证：内层 finally 执行后，遇到 return 时，外层 finally 仍会执行
    """
    global g_finally_executed
    try:
        try:
            g_finally_executed = 1
            raise ValueError("inner")
        except ValueError:
            g_finally_executed = 2
        finally:
            g_finally_executed = 3  # inner finally

        # inner finally 之后的 return
        g_finally_executed = 4
        return 50

    finally:
        g_finally_executed = 99  # outer finally 仍会执行


@test("NestedExceptions", "NestedFinallyWithReturnAfter")
def test_nested_finally_with_return_after():
    """测试内层 finally 之后 return 时外层 finally 的执行

    验证执行顺序：
    1. inner try 抛出异常
    2. inner except: g_finally_executed = 2
    3. inner finally: g_finally_executed = 3
    4. 正常代码: g_finally_executed = 4
    5. return 50（触发 goto outer finally）
    6. outer finally: g_finally_executed = 99
    7. 返回 50
    """
    global g_finally_executed
    g_finally_executed = 0
    result: int = nested_finally_with_return_after()
    EXPECT_EQ(result, 50)
    EXPECT_EQ(g_finally_executed, 99)  # outer finally 确实执行了


def nested_finally_with_break_after() -> int:
    """测试内层 finally 之后有 break 的场景（循环中）

    验证：内层 finally 执行后，遇到 break 时，外层 finally 仍会执行
    """
    global g_finally_executed
    count: int = 0

    for i in range(10):
        try:
            try:
                if i >= 3:
                    raise ValueError("test")
                count = count + 1
            except ValueError:
                count = count + 10
            finally:
                count = count + 100  # inner finally

            # inner finally 之后的代码
            if i == 5:
                break  # 触发 goto outer finally
            count = count + 1000

        finally:
            g_finally_executed = g_finally_executed + 1  # outer finally

    return count


@test("NestedExceptions", "NestedFinallyWithBreakAfter")
def test_nested_finally_with_break_after():
    """测试内层 finally 之后 break 时外层 finally 的执行

    验证执行流程：
    - i=0,1,2: count +1 +100 +1000 = 1101 * 3 = 3303, g_finally_executed +1 = 3
    - i=3,4: raise, count +10 +100 +1000 = 1110 * 2 = 5523, g_finally_executed +1 = 5
    - i=5: raise, count +10 +100 = 5633, break（跳过 +1000）, g_finally_executed +1 = 6
    - 最终 count = 5633
    """
    global g_finally_executed
    g_finally_executed = 0
    result: int = nested_finally_with_break_after()
    EXPECT_EQ(result, 5633)
    EXPECT_EQ(g_finally_executed, 6)  # 验证每次循环外层 finally 都执行了


def nested_finally_return_override() -> int:
    """测试外层 finally 的 return 覆盖内层 try 的 return

    验证 finally 的 return 覆盖规则在嵌套场景下的行为
    """
    global g_finally_executed
    try:
        try:
            g_finally_executed = 1
            return 10  # inner try 的 return
        finally:
            g_finally_executed = 2  # inner finally 执行
    finally:
        g_finally_executed = 3
        return 20  # type: ignore


@test("NestedExceptions", "NestedFinallyReturnOverride")
def test_nested_finally_return_override():
    """测试外层 finally 中的 return 覆盖内层 try 的 return

    验证：
    1. inner try return 10
    2. inner finally 执行（g_finally_executed: 0 → 1 → 2）
    3. outer finally 执行并 return 20（g_finally_executed: 2 → 3）
    4. 最终返回值为 20（outer finally 的 return 覆盖了 inner 的 return）
    """
    global g_finally_executed
    g_finally_executed = 0
    result: int = nested_finally_return_override()
    EXPECT_EQ(result, 20)  # outer finally 的 return 覆盖了 inner 的 return
    EXPECT_EQ(g_finally_executed, 3)  # 验证所有 finally 都执行了


def nested_finally_both_return() -> int:
    """测试内外层 finally 都有 return 的场景

    外层 finally 的 return 应该覆盖内层 finally 的 return
    """
    global g_finally_executed
    try:
        try:
            g_finally_executed = 1
            return 10  # inner try 的 return
        finally:
            g_finally_executed = 2
            return 30  # type: ignore
    finally:
        g_finally_executed = 3
        return 40  # type: ignore


@test("NestedExceptions", "NestedFinallyBothReturn")
def test_nested_finally_both_return():
    """测试内外层 finally 都有 return 时，外层覆盖内层

    验证：
    1. inner try return 10 被 inner finally return 30 覆盖
    2. inner finally return 30 被 outer finally return 40 覆盖
    3. 最终返回值为 40
    """
    global g_finally_executed
    g_finally_executed = 0
    result: int = nested_finally_both_return()
    EXPECT_EQ(result, 40)  # outer finally 的 return 最终生效
    EXPECT_EQ(g_finally_executed, 3)  # 所有代码块都执行了


# ============================================================================
# 12. 异常传播测试
# ============================================================================


def risky_function() -> None:
    """抛出异常的函数"""
    raise ValueError("function error")


@test("ExceptionPropagation", "ExceptionInFunction")
def test_exception_in_function():
    """测试函数中抛出的异常传播到调用者"""
    exception_caught: bool = False

    try:
        risky_function()
    except ValueError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


def inner_function() -> None:
    """内层函数抛出异常"""
    raise ValueError("inner error")


def outer_function() -> None:
    """外层函数调用内层函数"""
    inner_function()


@test("ExceptionPropagation", "ExceptionThroughCallChain")
def test_exception_through_call_chain():
    """测试异常通过调用链传播"""
    exception_caught: bool = False

    try:
        outer_function()
    except ValueError:
        exception_caught = True

    EXPECT_TRUE(exception_caught)


@test("ExceptionPropagation", "ExceptionRewrap")
def test_exception_rewrap():
    """测试捕获异常后抛出新异常

    内层抛出 ValueError，被捕获后重新包装为 RuntimeError
    """
    exception_caught: bool = False
    exception_message: str = ""

    try:
        try:
            value: int = 100
            raise ValueError(f"Inner error: {value}")
        except ValueError:
            msg: str = "Outer wrapper"
            raise RuntimeError(msg)
    except RuntimeError as e:
        exception_caught = True
        exception_message = str(e)

    EXPECT_TRUE(exception_caught)
    EXPECT_EQ(exception_message, "Outer wrapper")


# ============================================================================
# 13. 作用域测试
# ============================================================================


@test("Scope", "ExceptVariableScope")
def test_except_variable_scope():
    """测试 except 变量的作用域

    Python: except 的 as 变量仅在 except 块内可见
    C++: catch 块的变量仅在 catch 块内可见
    """
    caught: bool = False
    try:
        raise ValueError("test message")
    except ValueError as e:
        msg: str = str(e)
        caught = True
        EXPECT_TRUE(len(msg) > 0)

    # Python 中这里 e 不可访问（会被删除）
    # C++ 中这里 e 也不可访问（块作用域结束）
    EXPECT_TRUE(caught)


@test("Scope", "TryBlockVariableScope")
def test_try_block_variable_scope():
    """测试 try 块中变量的作用域

    按照 mcpy 设计：try 块中定义的变量在块外不可访问
    用户需要在外层显式声明
    """
    # 在外层声明变量
    x: int = 0

    try:
        x = 10  # 赋值，而不是声明
    except:
        pass

    # 外层可以访问（因为在外层声明）
    EXPECT_EQ(x, 10)


@test("Scope", "FinallyBlockScopeAccess")
def test_finally_block_scope_access():
    """测试 finally 块可以访问外层变量"""
    outer_var: int = 0
    inner_var: int = 0

    try:
        inner_var = 10
    finally:
        outer_var = 99  # 可以访问外层变量

    EXPECT_EQ(outer_var, 99)
    EXPECT_EQ(inner_var, 10)
